package com.kalvan.web.servlet.response;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.kalvan.sensitive.utils.SensitiveInfoUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;

/**
 * 统一返回对象
 *
 * @param <D> 表示data域对象
 * @author kalvan
 */
@Getter
@Setter
@ApiModel(value = "统一返回")
@Slf4j
public class R<D> extends HashMap<String, Object> {
    private static final long serialVersionUID = 1L;

    /**
     * 返回码
     */
    private static final String FIELD_CODE = "code";
    /**
     * 返回说明
     */
    private static final String FIELD_MSG = "msg";
    /**
     * 数据，分页时必须
     */
    private static final String FIELD_DATA = "data";
    /**
     * 数据,分页时必须
     */
    private static final String FIELD_COUNT = "count";


    /**
     * 返回
     *
     * @param code
     * @param msg
     */
    private R(int code, String msg) {
        super.put(FIELD_CODE, code);
        super.put(FIELD_MSG, msg);
    }

    /**
     * 设置返回数据data域-分页数据
     *
     * @param page
     * @return
     */
    public R<D> putPage(List page) {
        try {
            SensitiveInfoUtils.processObject(page);
        } catch (Exception e) {
            log.error("脱敏转换异常", e);
            return error("返回数据转换异常");
        }
        super.put(FIELD_DATA, page);
        super.put(FIELD_COUNT, ((Page) page).getTotal());
        return this;
    }

    /**
     * 设置返回数据data域,统一进行脱敏
     *
     * @param data
     * @return
     */
    public R<D> putData(Object data) {
        try {
            SensitiveInfoUtils.processObject(data);
        } catch (Exception e) {
            log.error("脱敏转换异常", e);
            return error("返回数据转换异常");
        }
        super.put(FIELD_DATA, data);
        return this;
    }

    /**
     * 设置返回数据
     *
     * @param key
     * @param value
     * @return
     */
    @Override
    public R put(String key, Object value) {
        try {
            SensitiveInfoUtils.processObject(value);
        } catch (Exception e) {
            log.error("脱敏转换异常", e);
            return error("返回数据转换异常");
        }
        super.put(key, value);
        return this;
    }

    @ApiModelProperty(value = "处理成功true/false 等价于code=0")
    public boolean isSuccess() {
        if (Code.CODE_SUCCESS.getCode() == (Integer) this.get(FIELD_CODE)) {
            return false;
        }
        return true;
    }


    /**
     * 成功 0成功
     *
     * @return
     */
    public static R ok() {
        return new R(Code.CODE_SUCCESS.getCode(), Code.CODE_SUCCESS.getMsg());
    }

    /**
     * 成功 0成功
     *
     * @return
     */
    public static R ok(String msg) {
        return new R(Code.CODE_SUCCESS.getCode(), msg);
    }

    /**
     * 失败返回 code=1
     *
     * @param msg
     * @return
     * @see
     */
    public static R error(String msg) {
        msg = StringUtils.isBlank(msg) ? "操作失败" : msg;
        return new R(Code.CODE_ERROR.getCode(), msg);
    }

    /**
     * 失败返回
     *
     * @param code
     * @param msg
     * @return
     * @see
     */
    public static R error(int code, String msg) {
        msg = StringUtils.isBlank(msg) ? "操作失败" : msg;
        return new R(code, msg);
    }

    public static R build(Code code) {
        return new R(code.getCode(), code.getMsg());
    }

    /**
     * 是否为ajax请求
     *
     * @param request
     * @return
     * @see
     */
    public static boolean isAjaxRequest(HttpServletRequest request) {
        String ajaxFlag = request.getHeader("X-Requested-With");
        return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag);
    }

    /**
     * http 拦截器异常返回
     *
     * @param response
     * @param r
     * @throws Exception
     */
    public static void returnResponse(HttpServletResponse response, R r) throws Exception {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(JSONObject.toJSONString(r));
        } catch (IOException e) {
            log.error(" 拦截器 response error", e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }
}
